﻿#ifndef __SOCKET__H__
#define __SOCKET__H__

#include <string>
#include <thread>
#include <mutex>
#include <queue>
#include <memory>
#include <atomic>
#include "cocos2d.h"
#include "Singleton.hpp"
using namespace  cocos2d;

template< typename T>
class ThreadSafeQueue
{
#define  LOCK(WHAT) std::lock_guard<std::mutex> locker(WHAT);

public:
	void pop()
	{
		LOCK(_mutex);
		_queue.pop();
	}
	void push(const T &t)
	{
		LOCK(_mutex);
		_queue.push(t);
	}
	const  T &  front()
	{
		LOCK(_mutex);
		return _queue.front();
	}
	bool empty()
	{
		LOCK(_mutex);
		bool ret = _queue.empty();
		return ret;
	}
private:
	std::mutex _mutex;
	std::queue<T> _queue;
};

class DataPack;

class Socket
{
	SingletonH(Socket)
public:

private:

public:
	/**
	 * @brief 发送请求接口
	 */
	void PushDataPack(DataPack *pack);
	void PushProtoData(const std::string &data);
	void PushRawData(const char *data, int size);
	void Connect(const std::string & ip, int port);
	void ReConnected();
	void DisConnected();
	bool IsConnected()
	{
		return this->isConnected;
	}
	~Socket();
	Socket();
private:

	void InitSocket();
	void OnConnected();
	void OnDisconnected();
	void ThreadFunc_Recv();
	void ProcessDataPack(DataPack*pack);
	void ThreadFunc_Send();

	ThreadSafeQueue<DataPack*> sendQueue;
	ThreadSafeQueue<DataPack*> recvQueue;
	int socket_client = 0;

	std::mutex read_write_mutex;
	std::atomic<bool> isConnected = false;
	bool isDisconnectedCall = false;
	std::string ip="0,0,0,0";
	int port = 0;
};

#endif
